package javabasics.nio;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/**
 * @Author suxiaoxiao
 * @Date 2019/6/2 17:46
 * @Version 1.0
 */
public class Niocopy {

    public static void main(String[] args) throws IOException {
        nioCopyFile("D:\\dubbox\\java8\\src\\main\\java\\javabasics\\nio\\zrz.txt",
                "D:\\dubbox\\java8\\src\\main\\java\\javabasics\\nio\\copy.txt");
    }

    /**
     * NIO
     *
     * 提升速度的那两个重要因素，Buffer and Channel
     *
     * @param resource
     * @param destination
     * @throws IOException
     */
    public static void nioCopyFile(String resource, String destination) throws IOException {
        // 文件输入流
        FileInputStream fis = new FileInputStream(resource);
        // 文件输出流
        FileOutputStream fos = new FileOutputStream(destination);

        // 读文件通道
        FileChannel readChannel = fis.getChannel();
        // 写文件通道
        FileChannel writeChannel = fos.getChannel();

        // 读入文件缓存区大小
        ByteBuffer buffer = ByteBuffer.allocate(1024);

        while (true) {
            // 重置缓冲区
            buffer.clear();
            int len = readChannel.read(buffer);
            // 如果读取不到文件 break
            if (len == -1) {
                break;
            }
            /**
             * Buffer有两种模式，写模式和读模式。
             * 在写模式下调用flip()之后，Buffer从写模式变成读模式。
             *
             * capacity: 在读/写模式下都是固定的，就是我们分配的缓冲大小（容量）。
             * position: 类似于读/写指针，表示当前读（写）到什么位置
             * limit: 在写模式下表示最多能写入多少数据，此时和capacity相同。
             *        在读模式下表示最多能读多少数据，此时和缓存中实际数据大小相同。
             *
             * public final Buffer flip() {
             *     // 要写入多少数据，此处应该为读取的大小。
             *     limit = position;
             *     position = 0;
             *     mark = -1;
             *     return this;
             * }
             *
             * rewind() 读取 Buffer 中有效数据做准备
             * position = 0; mark = -1; limit = limit;
             *
             * clear() 为重新写入数据做准备
             * position = 0; mark = -1; limit = capacity;
             *
             */
            buffer.flip();
            writeChannel.write(buffer);
        }
        // 关闭通道
        readChannel.close();
        writeChannel.close();
    }

}
